package com.ukefu.webim.util;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.snaker.engine.SnakerEngineFacets;
import org.snaker.engine.access.QueryFilter;
import org.snaker.engine.entity.Order;
import org.snaker.engine.entity.Task;

import com.ukefu.core.UKDataContext;
import com.ukefu.webim.service.cache.CacheHelper;
import com.ukefu.webim.service.es.ContactsRepository;
import com.ukefu.webim.service.repository.GenerationRepository;
import com.ukefu.webim.service.repository.ProcessContentRepository;
import com.ukefu.webim.service.repository.UserRepository;
import com.ukefu.webim.web.model.Contacts;
import com.ukefu.webim.web.model.Generation;
import com.ukefu.webim.web.model.MetadataTable;
import com.ukefu.webim.web.model.OrdersComment;
import com.ukefu.webim.web.model.ProcessContent;
import com.ukefu.webim.web.model.SysDic;
import com.ukefu.webim.web.model.TableProperties;
import com.ukefu.webim.web.model.UKeFuDic;
import com.ukefu.webim.web.model.User;
import com.ukefu.webim.web.model.WorkOrderType;
import com.ukefu.webim.web.model.WorkOrders;

public class WorkOrdersUtils {
	
	/**
	 * 加了同步功能 ， 写入数据库仅仅是为了保存，下次重启的时候 能够读取到正确的  开始位置 ， 写数据库的功能可以 放到异步执行中去
	 * @param orgi
	 * @return
	 */
	public synchronized static int getWorkOrderNumber(String orgi){
		GenerationRepository generationRes = UKDataContext.getContext().getBean(GenerationRepository.class) ;
		Generation generation = (Generation) CacheHelper.getSystemCacheBean().getCacheObject(UKDataContext.ModelType.WORKORDERS.toString() + "_" + orgi, orgi) ;
		long orderNumber = CacheHelper.getSystemCacheBean().getAtomicLong(UKDataContext.ModelType.WORKORDERS.toString() + "_" + orgi) ;
		if(generation == null){
			generation = generationRes.findByOrgiAndModel(orgi, UKDataContext.ModelType.WORKORDERS.toString()) ;
			if(generation == null){
				generation = new Generation() ;
				generation.setCreatetime(new Date());
				generation.setOrgi(orgi);
			}
		}
		generation.setModel(UKDataContext.ModelType.WORKORDERS.toString());
		generation.setStartinx((int) orderNumber);
		generationRes.save(generation) ;
		CacheHelper.getSystemCacheBean().put(UKDataContext.ModelType.WORKORDERS.toString() + "_" + orgi, generation, orgi);
		
		return (int) orderNumber ;
	}
	
	public static void processWorkOrders(List<WorkOrders> workOrdersList , UserRepository userRes , ContactsRepository contactsRes){
		if(workOrdersList.size() > 0){
			List<String> ids = new ArrayList<String>() , contacts = new ArrayList<String>();
			for(WorkOrders workOrders : workOrdersList){
				if(!StringUtils.isBlank(workOrders.getCreater()) && ids.size() < 1024){
					ids.add(workOrders.getCreater()) ;
					if(!StringUtils.isBlank(workOrders.getInitiator())){
						ids.add(workOrders.getInitiator()) ;
					}
					if(!StringUtils.isBlank(workOrders.getAccuser())){
						ids.add(workOrders.getAccuser()) ;
					}
				}
				if(!StringUtils.isBlank(workOrders.getCusid())){
					contacts.add(workOrders.getCusid()) ;
				}
			}
			List<User> users = null ;
			if(ids.size() > 0){
				users = userRes.findAll(ids) ;
			}
			Iterable<Contacts> contactsList = null ;
			if(contacts.size() > 0){
				contactsList = contactsRes.findAll(contacts) ;
			}
			for(WorkOrders workOrders: workOrdersList){
				if(users!=null){
					for(User user : users){
						if(user.getId().equals(workOrders.getCreater())){
							workOrders.setUser(user); 
						}
						if(user.getId().equals(workOrders.getAccuser())){
							workOrders.setCurrent(user);
						}
					}
				}
				if(contactsList != null){
					for(Contacts contact : contactsList){
						if(workOrders.getCusid()!=null && workOrders.getCusid().equals(contact.getId())){
							workOrders.setContacts(contact); break ;
						}
					}
				}
				
			}
		}
	}
	
	public static void processOrdersComment(List<OrdersComment> ordersCommentList , UserRepository userRes , ContactsRepository contactsRes){
		if(ordersCommentList.size() > 0){
			List<String> ids = new ArrayList<String>();
			for(OrdersComment ordersComment : ordersCommentList){
				if(ordersComment.getCreater()!=null && ids.size() < 1024){
					ids.add(ordersComment.getCreater()) ;
				}
			}
			List<User> users = userRes.findAll(ids) ;
			
			for(OrdersComment ordersComment: ordersCommentList){
				for(User user : users){
					if(user.getId().equals(ordersComment.getCreater())){
						ordersComment.setUser(user); 
						break ;
					}
				}
			}
		}
	}
	
	
	
	public static Map<String , Object> updateWorkflowParam(User user , WorkOrders workOrders , MetadataTable table){
		Map<String , Object> params = new HashMap<String , Object>();
		if(table!=null){
			for(TableProperties tp : table.getTableproperty()){
				if(tp.isSystemfield()){
					try {
						if(tp.isSeldata()){
							String value = BeanUtils.getProperty(workOrders, tp.getFieldname()) ;
							if(!StringUtils.isBlank(value)){
								List<SysDic> dics = UKeFuDic.getInstance().getDic(tp.getSeldatacode()) ;
								for(SysDic dic : dics){
									if(dic.getId().equals(value) || dic.getId().equals(value)){
										value = dic.getName() ; break ;
									}
								}
							}
							params.put(tp.getFieldname(), value) ;	//获取流程变量
						}else{
							params.put(tp.getFieldname(), BeanUtils.getProperty(workOrders, tp.getFieldname())) ;	//获取流程变量
						}
					} catch (IllegalAccessException | InvocationTargetException
							| NoSuchMethodException e) {
						e.printStackTrace();
					}
				}
			}
		}
		return params;
	}
	
	public static boolean createProcessInstance(SnakerEngineFacets facets , WorkOrderType workOrderType , User user , WorkOrders workOrders , MetadataTable table){
		boolean succ = false ;
		ProcessContentRepository processContentRepository = UKDataContext.getContext().getBean(ProcessContentRepository.class) ; 
		ProcessContent processContent = processContentRepository.findByIdAndOrgi(workOrderType.getProcessid(), workOrderType.getOrgi()) ;
		Map<String , Object> params = new HashMap<String , Object>();
		//启用流程，创建流程 , 需要从元数据获取 流程变量
		params.put("id", workOrders.getId()) ;
		
		if(processContent!=null && !StringUtils.isBlank(processContent.getProcessid())){
			org.snaker.engine.entity.Process process = facets.getEngine().process().getProcessById(processContent.getProcessid()) ;
			if(process!=null){
				if(table!=null){
					for(TableProperties tp : table.getTableproperty()){
						if(tp.isSystemfield()){
							try {
								if(tp.isSeldata()){
									String value = BeanUtils.getProperty(workOrders, tp.getFieldname()) ;
									SysDic sysDic = null ;
									if(!StringUtils.isBlank(value)){
										List<SysDic> dics = UKeFuDic.getInstance().getDic(tp.getSeldatacode()) ;
										for(SysDic dic : dics){
											if(dic.getId().equals(value) || dic.getId().equals(value)){
												value = dic.getName() ;sysDic = dic ; break ;
											}
										}
									}
									params.put(tp.getFieldname(), value) ;	//获取流程变量
								}else{
									params.put(tp.getFieldname(), BeanUtils.getProperty(workOrders, tp.getFieldname())) ;	//获取流程变量
								}
							} catch (IllegalAccessException | InvocationTargetException
									| NoSuchMethodException e) {
								e.printStackTrace();
							}
						}
					}
				}
				Order order = facets.startAndExecute(processContent.getProcessid() , user.getId() , user.getOrgan() , params) ;
				/**
				 * 添加流程变量，在 元数据中指定流程变量
				 */
				workOrders.setBpmid(processContent.getProcessid());
				workOrders.setMemo(order.getId());
				
				List<Task> tasks = facets.getEngine().query().getActiveTasks(new QueryFilter().setOrderId(order.getId()));
				if(tasks!=null && tasks.size() > 0){
					Task task = tasks.get(0) ;
					String[] actors = facets.getEngine().query().getTaskActorsByTaskId(task.getId());
	                if(actors!=null){
		                for(String actor : actors) {
		                	workOrders.setAccuser(actor);
		                }
	                }
				}
				succ = true ;
			}
		}
		return succ;
	}
}
